#ifndef DW_GRAPHICS_OPENGL_RENDERER_H
# define DW_GRAPHICS_OPENGL_RENDERER_H

#include "graphics/shader.h"
#include "graphics/renderer.h"

namespace dw {
	namespace graphics {
		namespace opengl {

class Renderer : public dw::graphics::Renderer
{
// Constructors
public:

	Renderer();

	virtual ~Renderer();

// Methods
public:

	bool supportExtension(const std::string&) const ;
	
	bool initExtensions() const ;

	virtual void setRenderState(const RenderState& renderState, const uint32 value);
	
	virtual void toggle(const RenderState& renderState);

	virtual void setViewport(const unsigned, const unsigned, const unsigned, const unsigned);
	
	virtual void setMatrixMode(const MatrixMode&);
	
	virtual void setColor(const Colorf& color);
	
	virtual void setColor(const float& r, const float& g, const float& b, const float& a);
	
	virtual void setPerspective(double, double, double, double);

	virtual void setOrtho2D(double, double, double, double, double, double);

	virtual void pushState();
	
	virtual void popState();
	
	virtual void setState(const State&);

	virtual void loadIdentity();
	
	virtual void pushMatrix();
	
	virtual void popMatrix();
	
	virtual void loadMatrix(const Matrix44f&);
	
	virtual void multMatrix(const Matrix44f&);
	
	virtual void setClipRect(const unsigned x, const unsigned y, const unsigned width, const unsigned height);



	virtual ITexture* createTexture();

	virtual IShader* createShader(const IShader::Type& type);

	virtual dw::graphics::Program* createProgram();



	virtual void setLight		(const int i, Light* light);
	
	virtual void setMaterial	(Material* material);

	virtual void setTexture(ITexture* texture);

	virtual void setTexture(const int i, ITexture* texture);
	
	virtual void setTextureUnit(const int i);

	virtual void setTextureUnitState(const int i, const TextureUnitState& tus, const uint32 value);

	virtual void setVertexBuffer(VertexBuffer* buffer);
	virtual void setIndexBuffer(IndexBuffer* buffer);

	virtual void setProgram(Program* program);
	
	void drawRect(const unsigned x, const unsigned y, const unsigned width, const unsigned height, const bool filled) const ;

	void drawCircle(const unsigned radius);

	void drawBox(const float& width, const float& height, const float& depth);

	void drawBox(const Cuboid& cuboid);

	void drawSphere(const float& radius);

	void drawTeapot(const float& size);

	void drawText(Font* font, const std::string& text);

	void drawGrid(const int size, const int unit);

public:

	static GLenum glDataType(const uint32 dataType);

	static GLenum glPrimitiveType(const uint32 primitiveType);

	static GLenum glTexEnv(const uint32 tus);

	static GLenum glTexOp(const uint32 top);

	static GLenum glTexArg(const uint32 texArg);

	static GLenum glTexAddressMode(const uint32 texAddressMode);

	static std::string glErrorString(const GLenum glError);

protected:

	std::string _extensions;

	static GLenum _glCullMode[3];
	
	static GLenum _glFillMode[3];
	
	static GLenum _glShadeMode[2];
	
	static GLenum _glBlendFunc[15];
	
	static GLenum _glBlendOp[6];
	
	static GLenum _glCmpFunc[8];

	static GLenum _glPixelFormat[6];

	unsigned _materialSwitchs;
};

} // namespace opengl
} // namespace graphics
} // namespace dw

#endif // DW_GRAPHICS_OPENGL_RENDERER_H
